package com.ztesoft.book.admin.config.schedule.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ztesoft.book.admin.config.schedule.service.ScheduleJobService;
import com.ztesoft.book.common.enums.ScheduleStatusEnum;
import com.ztesoft.book.common.utils.query.PageBO;
import com.ztesoft.book.common.utils.query.Query;
import com.ztesoft.book.core.quartz.schedulejob.dto.ScheduleJobDTO;
import com.ztesoft.book.core.quartz.schedulejob.mapper.ScheduleJobMapper;
import com.ztesoft.book.core.quartz.schedulejob.util.ScheduleUtils;
import org.apache.commons.lang3.StringUtils;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description 定时调度业务类
 * @Author YangFan
 * @Date 2021-04-15 15:35
 */
@Service("scheduleJobService")
public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobMapper, ScheduleJobDTO> implements ScheduleJobService {

    @Qualifier("schedulerFactoryBean")
    @Resource
    private Scheduler scheduler;


    /**
     * 方法功能描述:
     * < 项目启动时，初始化定时器 >
     *
     * @Return: void
     * @Author: YangFan
     * @Date: 2021-03-22 09:53
     */
    @PostConstruct
    public void init() {
        QueryWrapper<ScheduleJobDTO> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(ScheduleJobDTO::getSource, "admin");
        List<ScheduleJobDTO> scheduleJobDtoList = this.list(wrapper);
        for (ScheduleJobDTO scheduleJobDto : scheduleJobDtoList) {
            CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJobDto.getId());
            //如果不存在，则创建
            if (cronTrigger == null) {
                if (ScheduleUtils.isValidateCanDoExpression(scheduleJobDto.getCronExpression())) {
                    //校验定时任务是否可以执行，可执行则创建
                    ScheduleUtils.createJob(scheduler, scheduleJobDto);
                }
                else {
                    //删除过期任务
                    ScheduleUtils.deleteJob(scheduler, scheduleJobDto.getId());
                }
            }
            else {
                ScheduleUtils.updateJob(scheduler, scheduleJobDto);
            }
        }
    }


    @Override
    public PageBO queryPage(Map<String, Object> params) {
        String beanName = (String) params.get("beanName");

        IPage<ScheduleJobDTO> page = this.page(
                new Query<ScheduleJobDTO>().getPage(params),
                new QueryWrapper<ScheduleJobDTO>().like(StringUtils.isNotBlank(beanName), "bean_name", beanName)
        );

        return new PageBO(page);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveJob(ScheduleJobDTO scheduleJobDto) {
        scheduleJobDto.setStatus(ScheduleStatusEnum.NORMAL.getValue());
        this.save(scheduleJobDto);

        ScheduleUtils.createJob(scheduler, scheduleJobDto);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ScheduleJobDTO scheduleJobDto) {
        ScheduleUtils.updateJob(scheduler, scheduleJobDto);

        this.updateById(scheduleJobDto);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatch(String[] jobIds) {
        for (String jobId : jobIds) {
            ScheduleUtils.deleteJob(scheduler, jobId);
        }

        //删除数据
        this.removeByIds(Arrays.asList(jobIds));
    }


    @Override
    public int updateBatch(String[] jobIds, int status) {
        Map<String, Object> map = new HashMap<>(2);
        map.put("list", jobIds);
        map.put("status", status);
        return baseMapper.updateBatch(map);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void run(String[] jobIds) {
        for (String jobId : jobIds) {
            ScheduleUtils.run(scheduler, this.getById(jobId));
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pause(String[] jobIds) {
        for (String jobId : jobIds) {
            ScheduleUtils.pauseJob(scheduler, jobId);
        }

        updateBatch(jobIds, ScheduleStatusEnum.PAUSE.getValue());
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resume(String[] jobIds) {
        for (String jobId : jobIds) {
            ScheduleUtils.resumeJob(scheduler, jobId);
        }
        updateBatch(jobIds, ScheduleStatusEnum.NORMAL.getValue());
    }

}
